package org.pada.domain.config.consumer;

import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.pada.client.exception.SystemErrorCode;
import org.pada.client.exception.SystemException;
import org.pada.client.util.JsonUtil;

import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author shen.peng
 * @since 2024/9/18
 */
@Slf4j
public class RpcConsumerInvokeHandler2 implements InvocationHandler {

    private String domain;

    public RpcConsumerInvokeHandler2(String domain) {
        this.domain = domain;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Type returnType = method.getGenericReturnType();
        String url = String.format("%s/%s/%s", domain, method.getDeclaringClass().getName(), method.getName());
        String body = JsonUtil.toJSONString(args[0]);
        return exec(url, body, returnType);
    }

    private static OkHttpClient httpClient = new OkHttpClient.Builder()
            .connectTimeout(500L, TimeUnit.MILLISECONDS)
            .writeTimeout(5000L, TimeUnit.MILLISECONDS)
            .readTimeout(5000L, TimeUnit.MILLISECONDS).build();

    private static final MediaType JSON = MediaType.get("application/json; charset=utf-8");

    private Object exec(String url, String body, Type returnType) {
        Request request = new Request.Builder().url(url).post(RequestBody.create(body, JSON)).build();
        log.info("consumer url {} content {}", url, body);
        try (Response response = httpClient.newCall(request).execute()){
            ResponseBody resp = response.body();
            String data = Objects.nonNull(resp) ? resp.string() : null;
            log.info("consumer url {} resp {}", url, data);
            return JsonUtil.parseObject(data, returnType);
        } catch (IOException e) {
            log.error("rpc call exception", e);
            throw new SystemException(SystemErrorCode.RPC_CALL_EXCEPTION);
        }
    }
}
